package com.ddxcloud.movie.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddxcloud.common.constants.RedisKeyConstant;
import com.ddxcloud.common.handler.BusinessException;
import com.ddxcloud.common.utils.RedisUtil;
import com.ddxcloud.movie.config.alipay.AlipayConfiguration;
import com.ddxcloud.movie.data.constants.AlipayChannelConstant;
import com.ddxcloud.movie.data.dto.LoginAlipayDTO;
import com.ddxcloud.movie.data.dto.SmsLoginDTO;
import com.ddxcloud.movie.data.dto.WxLoginDTO;
import com.ddxcloud.movie.data.entity.Channel;
import com.ddxcloud.movie.data.entity.User;
import com.ddxcloud.movie.mapper.UserMapper;
import com.ddxcloud.movie.service.ActivityService;
import com.ddxcloud.movie.service.ChannelService;
import com.ddxcloud.movie.service.UserService;
import com.ddxcloud.movie.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    WxMaService wxMaService;

    @Resource
    AlipayConfiguration alipayConfiguration;

    @Resource
    AlipayClient alipayClient;

    @Resource
    ChannelService channelService;

    @Resource
    ActivityService activityService;

    @Resource
    RedisUtil redisUtil;

    @Override
    public User getUserByMobile(String mobile) {
        User user = new User();
        Integer isExist = this.baseMapper.isExistUserByUsername(mobile);
        if (isExist != null) {
            user = this.baseMapper.getByUsername(mobile);
        } else {
            user.setUsername(mobile);
            this.baseMapper.insert(user);
        }
        return user;
    }

    @Override
    public User loginByWechat(WxLoginDTO dto) throws WxErrorException {
        WxMaJscode2SessionResult sessionResult = wxMaService.jsCode2SessionInfo(dto.getCode());
        WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNoInfo(sessionResult.getSessionKey(), dto.getEncryptedData(), dto.getIv());
        Integer isExist = baseMapper.isExistUserByUsername(phoneInfo.getPurePhoneNumber());
        User user = new User();
        if (isExist == null) {
            user.setUsername(phoneInfo.getPhoneNumber());
            user.setWxOpenId(sessionResult.getOpenid());
            baseMapper.insert(user);
        } else {
            user = this.getUserByMobile(phoneInfo.getPhoneNumber());
        }
        redisUtil.setEx(RedisKeyConstant.LOGIN_USER + user.getUsername(), JSONUtil.toJsonStr(user), 30, TimeUnit.MINUTES);
        return user;
    }

    @Override
    public Map<String, Object> loginBySms(SmsLoginDTO dto) {
        String redisKey = RedisKeyConstant.SMS_LOGIN + dto.getPhone();
        if (!redisUtil.hasKey(redisKey)) {
            throw new BusinessException("验证码已过期");
        } else {
            if (!dto.getCodes().equals(redisUtil.get(redisKey))) {
                throw new BusinessException("验证码不正确");
            }
        }
        Integer isExist = baseMapper.isExistUserByUsername(dto.getPhone());
        User user = new User();
        if (isExist == null) {
            user.setUsername(dto.getPhone());
            baseMapper.insert(user);
            // activityService.getNewUserActivity(user);
        } else {
            user = this.getUserByMobile(dto.getPhone());
        }
        Map<String, Object> params = new HashMap<>();
        params.put("userId", user.getUserId());
        params.put("token", JwtUtil.createJWT(params));
        params.put("userInfo", user);
        params.put("exp", System.currentTimeMillis() + JwtUtil.timeMillis);
        return params;
    }

    @Override
    public void loginByAlipay(LoginAlipayDTO dto, HttpServletRequest request) {
        this.setChannel(request.getHeader("channelId"));
        AlipaySystemOauthTokenRequest oauthTokenRequest = new AlipaySystemOauthTokenRequest();
        oauthTokenRequest.setCode(dto.getCode());
        oauthTokenRequest.setGrantType(dto.getGrantType());
        try {
            AlipaySystemOauthTokenResponse response = alipayClient.execute(oauthTokenRequest);
            log.info("loginByAlipay response {}", response.getBody());
        } catch (AlipayApiException e) {
            log.error("loginByAlipay errMsg {}", e.getMessage());
        }
    }

    private void setChannel(String channelId) {
        Channel channel = channelService.getById(channelId);
        if (channel.getAlipayChannel().equalsIgnoreCase(AlipayChannelConstant.DG)) {
            alipayClient = new DefaultAlipayClient(
                    alipayConfiguration.getGateway_url(),
                    alipayConfiguration.getDg_h5_app_id(),
                    alipayConfiguration.getDg_h5_merchant_private_key(),
                    alipayConfiguration.getFormat(),
                    alipayConfiguration.getCharset(),
                    alipayConfiguration.getDg_h5_alipay_public_key(),
                    alipayConfiguration.getSign_type()
            );
        } else if (channel.getAlipayChannel().equalsIgnoreCase(AlipayChannelConstant.ZH)) {
            alipayClient = new DefaultAlipayClient(
                    alipayConfiguration.getGateway_url(),
                    alipayConfiguration.getZh_h5_app_id(),
                    alipayConfiguration.getZh_h5_merchant_private_key(),
                    alipayConfiguration.getFormat(),
                    alipayConfiguration.getCharset(),
                    alipayConfiguration.getZh_h5_alipay_public_key(),
                    alipayConfiguration.getSign_type()
            );
        }
    }
}
